package cn.hamster3.mc.plugin.core.velocity;

import cn.hamster3.mc.plugin.core.common.api.CoreAPI;
import cn.hamster3.mc.plugin.core.common.config.YamlConfig;
import cn.hamster3.mc.plugin.core.common.util.UpdateCheckUtils;
import cn.hamster3.mc.plugin.core.velocity.api.CoreVelocityAPI;
import com.google.inject.Inject;
import com.velocitypowered.api.event.PostOrder;
import com.velocitypowered.api.event.Subscribe;
import com.velocitypowered.api.event.proxy.ProxyInitializeEvent;
import com.velocitypowered.api.event.proxy.ProxyShutdownEvent;
import com.velocitypowered.api.plugin.Plugin;
import com.velocitypowered.api.plugin.PluginContainer;
import com.velocitypowered.api.plugin.annotation.DataDirectory;
import com.velocitypowered.api.proxy.ProxyServer;
import com.zaxxer.hikari.HikariDataSource;
import lombok.Getter;
import net.kyori.adventure.text.Component;
import org.slf4j.Logger;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;

@Plugin(
        id = "hamster-core",
        name = "HamsterCore",
        version = BuildConstants.VERSION,
        description = BuildConstants.DESCRIPTION,
        authors = {"MiniDay"}
)
public class HamsterCorePlugin {
    @Getter
    private static HamsterCorePlugin instance;
    @Getter
    private final java.util.logging.Logger logger;
    @Getter
    private final Logger slf4jLogger;
    @Getter
    private final ProxyServer proxyServer;
    @Getter
    private final File dataFolder;

    @Inject
    public HamsterCorePlugin(Logger slf4jLogger, ProxyServer proxyServer, @DataDirectory Path dataPath) {
        logger = java.util.logging.Logger.getLogger("hamster-core");
        this.slf4jLogger = slf4jLogger;
        this.proxyServer = proxyServer;
        dataFolder = dataPath.toFile();
        instance = this;
        long start = System.currentTimeMillis();
        try {
            if (dataFolder.mkdir()) {
                slf4jLogger.info("已生成插件存档文件夹");
            }
            File configFile = new File(dataFolder, "config.yml");
            if (!configFile.exists()) {
                try (InputStream stream = HamsterCorePlugin.class.getResourceAsStream("/config.yml")) {
                    if (stream != null) {
                        Files.copy(stream, configFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
                    }
                }
            }
            CoreVelocityAPI.init(configFile);
            slf4jLogger.info("已初始化 CoreAPI");
        } catch (Exception e) {
            slf4jLogger.error("初始化 CoreAPI 出错", e);
        }
        long time = System.currentTimeMillis() - start;
        slf4jLogger.info("HamsterCore 初始化完成，总计耗时 " + time + " ms");
    }

    @Subscribe(order = PostOrder.FIRST)
    public void onProxyInitialization(ProxyInitializeEvent event) {
        long start = System.currentTimeMillis();
        slf4jLogger.info("仓鼠核心正在启动");
        long time = System.currentTimeMillis() - start;
        slf4jLogger.info("仓鼠核心启动完成，总计耗时 " + time + " ms");
        CoreAPI.getInstance().getExecutorService().submit(() -> {
            for (PluginContainer plugin : proxyServer.getPluginManager().getPlugins()) {
                String pluginName = plugin.getDescription().getName().orElse(null);
                if (pluginName == null) {
                    continue;
                }
                Object pluginObject = plugin.getInstance().orElse(null);
                if (pluginObject == null) {
                    continue;
                }
                try (InputStream stream = pluginObject.getClass().getResourceAsStream("/update.yml")) {
                    if (stream == null) {
                        continue;
                    }
                    try (InputStreamReader reader = new InputStreamReader(stream, StandardCharsets.UTF_8)) {
                        YamlConfig config = YamlConfig.load(reader);
                        UpdateCheckUtils.showUpdate(pluginName, config, (s) -> proxyServer.sendMessage(Component.text(s)));
                    } catch (IOException ignored) {
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        });
    }

    @Subscribe(order = PostOrder.LAST)
    public void onProxyShutdown(ProxyShutdownEvent event) {
        long start = System.currentTimeMillis();
        CoreAPI.getInstance().getJedisPool().close();
        slf4jLogger.info("已关闭 Redis 连接池");
        if (CoreAPI.getInstance().getDataSource() instanceof HikariDataSource dataSource) {
            dataSource.close();
            slf4jLogger.info("已关闭数据库连接池");
        }
        CoreAPI.getInstance().getExecutorService().shutdownNow();
        slf4jLogger.info("已关闭 ExecutorService 线程池");
        CoreAPI.getInstance().getScheduledService().shutdownNow();
        slf4jLogger.info("已关闭 ScheduledExecutorService 线程池");
        long time = System.currentTimeMillis() - start;
        slf4jLogger.info("HamsterCore 关闭完成，总计耗时 " + time + " ms");
    }
}